﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CarbonExchange.AmeeQuery;

namespace CarbonExchange.Bll
{
    public class AmeeProfileItemFactory : AmeeFactoryBase<AmeeProfileItem>
    {
        public AmeeProfileItemFactory() : base()
        {
        }

        public AmeeProfileItemFactory(IAmeeCommand command) : base(command)
        {
        }

        public AmeeProfileItem GetByPath(string profileId, string path, string id)
        {
            var xml = Command.SendXmlGet(BuildAmeeProfilePath(profileId, path, id));
            if (xml != null)
            {
                var tmp = new AmeeProfileItem();
                var profileItemResource = xml.Root.Element("ProfileItemResource");
                if (profileItemResource != null)
                {
                    var profileItem = xml.Root.Element("ProfileItemResource").Element("ProfileItem");
                    tmp.Name = profileItem.Element("Name").Value;
                    tmp.ValidFrom = ConvertToAmeeDate(profileItem.Element("ValidFrom").Value);
                    tmp.Created = ConvertToAmeeDate(profileItem.Attribute("created").Value);
                    tmp.Id = profileItem.Attribute("uid").Value;
                    tmp.DataItemId = profileItem.Element("DataItem").Attribute("uid").Value;
                    tmp.Path = xml.Root.Element("ProfileItemResource").Element("Path").Value;
                    tmp.ProfileId = xml.Root.Element("ProfileItemResource").Element("Profile").Attribute("uid").Value;
                    tmp.AmountPerMonth = string.IsNullOrEmpty(profileItem.Element("AmountPerMonth").Value) ? 0 : decimal.Parse(profileItem.Element("AmountPerMonth").Value);
                    var itemValues = profileItem.Element("ItemValues").Elements("ItemValue").Select(x => new AmeeProfileItemProperty(
                        x.Element("ItemValueDefinition").Element("ValueDefinition").Element("ValueType").Value,
                        x.Element("Name").Value,
                        x.Element("Value").Value,
                        x.Element("Path").Value)).ToList();
                    tmp.ItemValues = itemValues;
                    return tmp;
                }
                else
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
        }

        public AmeeProfileItem CreateItem(AmeeDataCatagory dataItem, string profileId, string name, DateTime validFrom)
        {
            if (dataItem == null)
            {
                throw new ArgumentNullException("dataItem");
            }

            if (!dataItem.DataItemSelected)
            {
                throw new ApplicationException("DataItem has not selected the DataItem");
            }

            var tmp = new AmeeProfileItem();
            tmp.DataItemId = dataItem.Id;
            tmp.ValidFrom = new DateTime(validFrom.Year, validFrom.Month, 1);
            tmp.Name = DateTime.UtcNow.ToString("F");
            tmp.ProfileId = profileId;
            tmp.Path = dataItem.Path;

            return tmp;
        }

        public void Save(AmeeProfileItem item)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("name", item.Name);
            data.Add("validFrom", ConvertToShortAmeeDate(item.ValidFrom));
            
            if (item.ItemValues == null)
            {
                item.ItemValues = new List<AmeeProfileItemProperty>();
            }

            foreach (var prop in item.ItemValues)
            {
                data.Add(prop.Path, prop.GetAmeeValue());
            }

            if (string.IsNullOrEmpty(item.Id))
            {
                //save inital version
                var insertXml = Command.SendXmlInsert(BuildAmeeProfilePath(item.ProfileId, item.Path), item.DataItemId, data);
                var profileItem = insertXml.Root.Element("ProfileCategoryResource").Element("ProfileItem");
                item.Id = profileItem.Attribute("uid").Value;
                item.Path = string.Concat(item.Path, "/", item.Id);


                //get the dataitems back
                var xmlItemValues = profileItem.Element("ItemValues").Elements("ItemValue");
                foreach (var xmlItemValue in xmlItemValues)
                {
                    var tmp = item.ItemValues.Where(x => x.Path == xmlItemValue.Element("Path").Value).SingleOrDefault();
                    if (tmp == null)
                    {
                        tmp = new AmeeProfileItemProperty(
                            xmlItemValue.Element("ItemValueDefinition").Element("ValueDefinition").Element("ValueType").Value,
                            xmlItemValue.Element("Name").Value,
                            xmlItemValue.Element("Value").Value,
                            xmlItemValue.Element("Path").Value);
                        item.ItemValues.Add(tmp);
                    }
                    else
                    {
                        //set the name as it wont have been set yet, only the path will have done when creating the property
                        tmp.Name = xmlItemValue.Element("Name").Value;
                    }
                }
                var xmlProfilItem = insertXml.Root.Element("ProfileCategoryResource").Element("ProfileItem");
                //set to now as amee dosn't return this
                item.Created = DateTime.Now;
                item.AmountPerMonth = decimal.Parse(xmlProfilItem.Element("AmountPerMonth").Value);
            }
            else
            {
                var updateXml = Command.SendXmlUpdate(BuildAmeeProfilePath(item.ProfileId, item.Path), data);
                var xmlProfilItem = updateXml.Root.Element("ProfileItemResource").Element("ProfileItem");
                item.Created = ConvertToAmeeDate(xmlProfilItem.Attribute("created").Value);
                item.AmountPerMonth = decimal.Parse(xmlProfilItem.Element("AmountPerMonth").Value);
            }
        }

        public void Delete(AmeeProfileItem item)
        {
            Command.SendXmlDelete(BuildAmeeProfilePath(item.ProfileId, item.Path));
        }

        public void Delete(string profileId, string path, string id)
        {
            Command.SendXmlDelete(BuildAmeeProfilePath(profileId, path, id));
        }
    }
}
